package at.ac.univie.zsu.aguataplan.video.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.net.io.CopyStreamAdapter;
import org.apache.commons.net.io.CopyStreamException;
import org.apache.commons.net.io.Util;
import org.apache.log4j.Logger;

import at.ac.univie.zsu.aguataplan.exception.FileHandlingException;
import at.ac.univie.zsu.aguataplan.util.Constants;
import at.ac.univie.zsu.aguataplan.video.IVideoService;

/**
 * @author gerry
 * 
 */

public class FileHandling implements Constants {
	private static Logger log = Logger.getLogger(FileHandling.class);

	private IVideoService iVideoService;

	private long size;

	// ----------------------------------------------------
	// CONSTRUCTOR
	// ----------------------------------------------------

	public FileHandling(IVideoService iVideoService) {
		this.iVideoService = iVideoService;
	}

	// ----------------------------------------------------
	// METHODS
	// ----------------------------------------------------

	/**
	 * copy a file to an already existing directory
	 * 
	 * @param src
	 * @param dst
	 * @return
	 * @throws FileHandlingException
	 */
	public void cpFile(String dirInput, String fileInput, String dirOutput,
			String fileOutput) throws FileHandlingException {
		long t;
		t = System.currentTimeMillis();

		File src = new File(dirInput + Sep + fileInput);
		File dst = new File(dirOutput + Sep + fileOutput);

		InputStream is;
		OutputStream os;

		try {
			is = new FileInputStream(src);
			os = new FileOutputStream(dst);

			final long length = src.length();
			size = length / 10;

			Util.copyStream(is, os, Util.DEFAULT_COPY_BUFFER_SIZE, length,
					new CopyStreamAdapter() {
						@Override
						public void bytesTransferred(
								long totalBytesTransferred,
								int bytesTransferred, long streamSize) {

							if (totalBytesTransferred > size) {
								size = size + length / 10;
								double d = (double) totalBytesTransferred
										/ streamSize;
								log.debug("% " + d);

								int progress = (int) Math.floor(d * 100);

								if (iVideoService != null) {
									iVideoService.setProgressFile((int) Math
											.floor(progress));
								}
							}

						}
					});

			os.flush();
			os.close();
			is.close();
		} catch (FileNotFoundException e) {
			throw new FileHandlingException(e.toString(),
					RET_ERR_FILE_NOT_FOUND);
		} catch (CopyStreamException e) {
			throw new FileHandlingException(e.toString(), RET_ERR_COPY_STREAM);
		} catch (IOException e) {
			throw new FileHandlingException(e.toString(), RET_ERR_IO);
		}

		t = (System.currentTimeMillis() - t);

		log.info(src + " --> " + dst + " done in " + t + "ms");

	}

	public void delFile(String dirInput, String fileInput)
			throws FileHandlingException {
		boolean success;
		long t;
		t = System.currentTimeMillis();

		File src = new File(dirInput + Sep + fileInput);

		if (!src.exists()) {
			throw new FileHandlingException("File " + fileInput
					+ " does not exist!", RET_ERR_FILE_NOT_FOUND);
		}

		if (!src.canWrite()) {
			throw new FileHandlingException("File " + fileInput
					+ " is not writeable!", RET_ERR_NO_ACCESS);
		}

		if (!src.isFile()) {
			throw new FileHandlingException("File " + fileInput
					+ " is not a file!", RET_ERR_WRONG_FILE_TYPE);
		}

		success = src.delete();

		if (!success) {
			throw new FileHandlingException("Delete file " + fileInput
					+ " does not work!", RET_ERR_FILE_DELETE_FAILED);
		}

		t = (System.currentTimeMillis() - t);

		log.info(src + " deleted in " + t + "ms");
	}

}
